package com.bootnetty.adapter;

import com.bootnetty.entity.Result;
import com.bootnetty.entity.Station;
import com.bootnetty.entity.User;
import com.bootnetty.utils.CommandUtils;
import com.bootnetty.utils.DBUtils;
import com.bootnetty.utils.StringUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;


public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private ByteBuf buf;

    /**
     * 从客户端收到新的数据时，这个方法会在收到消息时被调用
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception, IOException {
        //System.out.println("channelRead:read msg:"+msg.toString());
        //从buf数组中获取数据
        //ByteBuf buff = (ByteBuf) msg;
        byte[] bytes = (byte[]) msg;
        String info = StringUtils.byteArrayToHexString(bytes, true);

        logger.info("channelRead:read msg:" + info.toString());
        //User user = DBUtils.test(1);
        //User user = userService.Sel(1);
        //System.out.println(user.getRealName());
        /*Station station = new Station();
        station.setHMode(1);
        station.setTMode(1);
        station.setSerialNum(2199023255555L);
        station.setHSatus(1);
        station.setTSatus(1);
        station.setActive(1);
        station.setExpectTemperature(1.0);
        station.setExpectHumidity(1.0);
        DBUtils.updateStation(station);*/
        //Result result = DBUtils.getStationConfig(63L);
        //System.out.println(result.getIDs());

        Result result = DBUtils.getStationConfig(63L);
        result.setDataID("111");
        result.setPid("32235555");
        result.setDataType("1");
        String[] sendMessage = CommandUtils.codeCommand(result);
        for(int i=0;i<sendMessage.length;i++) {
            byte[] res = StringUtils.hexStr2Byte(sendMessage[i]);
           // System.out.println(res.toString());
            //使用流的方式传回去
            ByteBuf byteBuf = ctx.alloc().buffer();
            byteBuf.writeBytes(res);
            if (byteBuf != null) {
                //回应客户端
                ctx.writeAndFlush(byteBuf);
            }
            Thread.sleep(1000);
        }
    }

    /**
     * 从客户端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException {
        //System.out.println("channelReadComplete");
        logger.info("channelReadComplete");
        ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException {
        //System.out.println("exceptionCaught");
        logger.error(cause.getMessage());
        cause.printStackTrace();
        ctx.close();//抛出异常，断开与客户端的连接
    }

    /**
     * 客户端与服务端第一次建立连接时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelActive(ctx);
        ctx.channel().read();
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        //此处不能使用ctx.close()，否则客户端始终无法与服务端建立连接
        logger.info("channelActive:" + clientIp + ctx.name());
        //System.out.println("channelActive:"+clientIp+ctx.name());
    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelInactive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费，并发量很大情况下可能造成宕机
        //System.out.println("channelInactive:"+clientIp);
        logger.info("channelInactive:" + clientIp);
    }

    /**
     * 服务端当read超时, 会调用这个方法
     *
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception, IOException {
        super.userEventTriggered(ctx, evt);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ctx.close();//超时时断开连接
        //System.out.println("userEventTriggered:"+clientIp);
        logger.info("userEventTriggered:" + clientIp);
    }
}
